"""
订单相关的 Celery 任务
"""
import asyncio
from celery import Task
from datetime import datetime, timedelta
from celery_app import celery_app
from models.models import UserOrder
from tortoise import Tortoise


class DatabaseTask(Task):
    """
    自定义任务基类，确保每个任务执行时数据库连接可用
    注意：由于 Celery 任务在独立进程中运行，每次任务执行时都需要初始化数据库连接
    """
    pass


async def _cancel_order_async(order_no: str):
    """
    异步取消订单的内部函数
    """
    try:
        # 确保数据库连接已初始化
        from config.config_dev import TORTOISE_ORM
        if not Tortoise._inited:
            await Tortoise.init(config=TORTOISE_ORM)
        
        # 查询订单
        order = await UserOrder.get_or_none(order_no=order_no)
        
        if not order:
            print(f"订单 {order_no} 不存在，任务取消")
            return {"status": "not_found", "order_no": order_no}
        
        # 检查订单状态
        if order.status != 0:  # 0 表示待支付
            print(f"订单 {order_no} 状态已变更（当前状态: {order.status}），无需取消")
            return {"status": "already_processed", "order_no": order_no, "current_status": order.status}
        
        # 检查订单创建时间，确保已经超过15分钟
        create_time = order.create_time or datetime.now()
        elapsed_time = (datetime.now() - create_time).total_seconds() / 60  # 转换为分钟
        
        if elapsed_time < 15:
            # 如果还没到15分钟，返回需要重试的标识
            remaining_seconds = (15 * 60) - (elapsed_time * 60)
            print(f"订单 {order_no} 还未到15分钟（已过 {elapsed_time:.1f} 分钟），将在 {remaining_seconds:.0f} 秒后重试")
            raise Exception(f"订单还未到15分钟，剩余 {remaining_seconds:.0f} 秒")
        
        # 更新订单状态为已取消（状态码2）
        order.status = 2
        await order.save(update_fields=["status", "update_time"])
        
        print(f"订单 {order_no} 已自动取消（超时未支付）")
        
        # 这里可以添加其他业务逻辑，比如：
        # - 释放库存
        # - 发送通知给用户
        # - 记录日志等
        
        return {
            "status": "cancelled",
            "order_no": order_no,
            "cancelled_at": datetime.now().isoformat()
        }
    finally:
        # 关闭数据库连接
        if Tortoise._inited:
            await Tortoise.close_connections()


@celery_app.task(
    base=DatabaseTask,
    bind=True,
    name="tasks.order_tasks.cancel_unpaid_order",
    max_retries=3,  # 最大重试次数
    default_retry_delay=60,  # 重试延迟（秒）
)
def cancel_unpaid_order(self, order_no: str):
    """
    取消未支付的订单任务（同步包装器）
    
    Args:
        order_no: 订单号
    """
    try:
        # 创建新的事件循环来运行异步代码
        # 注意：Celery 任务在独立进程中运行，需要创建新的事件循环
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            result = loop.run_until_complete(_cancel_order_async(order_no))
            return result
        finally:
            # 确保关闭事件循环
            try:
                # 取消所有待处理的任务
                pending = asyncio.all_tasks(loop)
                for task in pending:
                    task.cancel()
                # 等待所有任务完成
                if pending:
                    loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
            except Exception:
                pass
            finally:
                loop.close()
            
    except Exception as exc:
        error_msg = str(exc)
        print(f"取消订单 {order_no} 时发生错误: {error_msg}")
        
        # 如果是"还未到15分钟"的错误，计算重试时间
        if "还未到15分钟" in error_msg:
            # 从错误消息中提取剩余秒数
            try:
                import re
                match = re.search(r'剩余 (\d+\.?\d*) 秒', error_msg)
                if match:
                    remaining_seconds = float(match.group(1))
                    raise self.retry(countdown=int(remaining_seconds), exc=exc)
            except:
                pass
        
        # 如果重试次数未用完，则重试
        if self.request.retries < self.max_retries:
            raise self.retry(exc=exc)
        else:
            return {"status": "failed", "order_no": order_no, "error": error_msg}

